package com.cndw.kungfu.model.pve;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import com.cndw.kungfu.config.ConstantsLog;
import com.cndw.kungfu.config.ConstantsRadio;
import com.cndw.kungfu.domain.Monster;
import com.cndw.kungfu.domain.Player;
import com.cndw.kungfu.domain.Union;
import com.cndw.kungfu.ext.TimeProcesser;
import com.cndw.kungfu.model.Context;
import com.cndw.kungfu.model.battle.FighterMonster;
import com.cndw.kungfu.model.pve.domain.UnionPetConfig;
import com.cndw.kungfu.model.sys.LogServer;
import com.cndw.kungfu.vo.EventNotice;
import com.cndw.kungfu.vo.UnionPetAkVO;

public class UnionPet {
	
	private int lastOpenTime;
	
	private int monsterId;
	private int currentSamllDam = 0;
	private FighterMonster unionPetFighter;
	private int unionPetHpMax = 0;
	private int unionId;
	private int type;
	
	private Map<Long, Integer> playerDamMap = new ConcurrentHashMap<Long, Integer>();
	private Map<Long, Integer> playerAkMap = new ConcurrentHashMap<Long, Integer>();
	
	private Map<Long, Integer> buffMap = new ConcurrentHashMap<Long, Integer>();
	/**
	 * 奖励加成
	 */
	private Map<Long, Integer> awardCoffMap = new ConcurrentHashMap<Long, Integer>();
	/**
	 * 玩家死亡复活时间
	 */
	private Map<Long, Integer> playerDeadMap = new ConcurrentHashMap<Long, Integer>();
	
	private ConcurrentHashMap<Long,Boolean> allPlayers = new ConcurrentHashMap<Long,Boolean>();
	
	public UnionPet(int unionId, int type) {
		this.unionId = unionId;
		this.type = type;
		monsterId = type == 0 ? 2003 : 2004;
		lastOpenTime = TimeProcesser.getUnixTime();
		Monster monster = Context.getUndercityServer().getMonster(monsterId);
		if (monster != null) {
			unionPetFighter = monster.fighter();
			Union union = Context.getUnionServer().getUnionById(unionId);
			unionPetHpMax = 5 * union.getPetLv() * (monster.getHp() / 100);//当前等级神兽生命=神兽等级*5%(精项15%)*怪物表中怪物生命
			unionPetFighter.getSourceObject().setHp(unionPetHpMax);
			unionPetFighter.getSourceObject().setMaxHp(unionPetHpMax);
			if (type == 1) {//精英修改攻击、防御
				int attack = (100 + union.getPetLv() * 2) * (monster.getAttack() / 100);
				int defense = (100 + union.getPetLv() * 3) * (monster.getDefense() / 100);
				unionPetFighter.getSourceObject().setAttack(attack);
				unionPetFighter.getSourceObject().setDefense(defense);
			}
		}
	}
	
	public int getLastOpenTime() {
		return lastOpenTime;
	}
	
	public void addPlayer(long playerId) {
		allPlayers.put(playerId, true);
	}
	
	public void addBuff(long playerId, int add) {
		if (!buffMap.containsKey(playerId)) {
			buffMap.put(playerId, add);
		} else {
			buffMap.put(playerId, buffMap.get(playerId) + add);
		}
	}
	
	public void addAwardCoff(long playerId, int add) {
		if (!awardCoffMap.containsKey(playerId)) {
			awardCoffMap.put(playerId, add);
		} else {
			awardCoffMap.put(playerId, awardCoffMap.get(playerId) + add);
		}
	}
	
	public int getBuff(long playerId) {
		if (!buffMap.containsKey(playerId)) {
			return 0;
		}
		return buffMap.get(playerId);
	}
	
	public int getAwardCoff(long playerId) {
		if (!awardCoffMap.containsKey(playerId)) {
			return 0;
		}
		return awardCoffMap.get(playerId);
	}
	
	public void playerDeadSet(long playerId, int time) {
		if (time == 0) {
			playerDeadMap.remove(playerId);
		} else {
			playerDeadMap.put(playerId, time);
		}
	}
	
	public int playerDeadGet(long playerId) {
		if (playerDeadMap.containsKey(playerId)) {
			return playerDeadMap.get(playerId);
		}
		return 0;
	}
	
	public void alterDam(long playerId, int dam) {
		int times = 1;
		if (playerDamMap.containsKey(playerId)) {
			dam += playerDamMap.get(playerId);
			times += playerAkMap.get(playerId);
		}
		playerDamMap.put(playerId, dam);
		playerAkMap.put(playerId, times);
		if (dam >= currentSamllDam || playerAkMap.size() <= 10) {
			broadcastOrder(0);// 广播全线血量变化
		} else {
			broadcastHp();
		}
	}
	
	public void broadcastHp() {
		EventNotice notice = new EventNotice(ConstantsRadio.unionPet, ConstantsRadio.unionPet_orderList);
		notice.put("unionPetMaxHp", unionPetHpMax);
		notice.put("unionPetHp", unionPetFighter == null ? 0 : unionPetFighter.getHp());
		
		notice.broadcast(allPlayers.keySet());
		
	}
	
	public void broadcastDead() {
	
		EventNotice notice = new EventNotice(ConstantsRadio.unionPet, ConstantsRadio.unionPet_dead);
//			notice.put("", value);
		notice.broadcast(allPlayers.keySet());
		
	}
	
	public void broadcastOrder(long playerId) {
		EventNotice notice = new EventNotice(ConstantsRadio.unionPet, ConstantsRadio.unionPet_orderList);
		notice.put("curOrder", currentAkOrder());
		notice.put("unionPetMaxHp", unionPetHpMax);
		notice.put("unionPetHp", unionPetFighter == null ? 0 : unionPetFighter.getHp());
		
		if (playerId > 0) {
			notice.broadcast(playerId);
		} else {
			notice.broadcast(allPlayers.keySet());
		}
	}
	
	public int getDamById(long playerId) {
		if (playerDamMap.containsKey(playerId)) {
			return playerDamMap.get(playerId);
		}
		return 0;
	}
	
	public int getAkTimes(long playerId) {
		if (!playerAkMap.containsKey(playerId)) {
			return 0;
		}
		return playerAkMap.get(playerId);
	}
	
	public FighterMonster getPetFighter() {
		return unionPetFighter;
	}

	public void setUnionPetFighter(FighterMonster unionPetFighter) {
		this.unionPetFighter = unionPetFighter;
	}
	
	private ArrayList<Entry<Long, Integer>> damList() {
		ArrayList<Entry<Long, Integer>> newList = new ArrayList<Entry<Long, Integer>>(playerDamMap.entrySet());

		Collections.sort(newList, new Comparator<Map.Entry<Long, Integer>>() {
			public int compare(Map.Entry<Long, Integer> o1, Map.Entry<Long, Integer> o2) {
				return (o2.getValue() - o1.getValue());
			}
		});
		return newList;
	}
	
	public List<UnionPetAkVO> currentAkOrder() {
		ArrayList<Entry<Long, Integer>> newList = damList();
		List<UnionPetAkVO> orderList = new ArrayList<UnionPetAkVO>();
		int orderId = 0;
		for (Entry<Long, Integer> e : newList) {
			orderId++;
			long playerId = e.getKey();
			int akNum = playerAkMap.get(playerId);
			int damNum = playerDamMap.get(playerId);
			UnionPetAkVO akVo = new UnionPetAkVO(playerId, orderId, akNum, damNum);
			orderList.add(akVo);

			if (orderId == 10) {
				currentSamllDam = damNum;
			}
			if (orderId >= 10) {
				break;
			}
		}
		return orderList;
	}
	
	public void orderDam() {
		ArrayList<Entry<Long, Integer>> newList = damList();
		List<UnionPetAkVO> orderList = new ArrayList<UnionPetAkVO>();
		Union union = Context.getUnionServer().getUnionById(unionId);
		int orderId = 0;
		UnionPetConfig config = UnionPetConfig.getOne(union.getPetLv());
		List<Object[]> orderOneUnion = new ArrayList<Object[]>();
		for (Entry<Long, Integer> e : newList) {
			orderId++;

			long playerId = e.getKey();
			int akNum = playerAkMap.get(playerId);
			int damNum = playerDamMap.get(playerId);
			UnionPetAkVO akVo = new UnionPetAkVO(playerId, orderId, akNum, damNum);
			orderList.add(akVo);
			if (orderId == 1) {
				UnionPetBattle.getInstance().addLastAkPlayer(unionId, playerId);//设定最后一击者
				UnionPetBattle.getInstance().commitSync();
			}
			Player player = Context.getPlayerServer().getByPlayerId(playerId);
			if (orderId <= 3) {
				Object[] orderObj = new Object[4];
				
				orderObj[0] = orderId;
				orderObj[1] = player.getPlayerName();
				orderObj[2] = damNum;
				orderObj[3] = ((int)(1f * damNum / unionPetHpMax * 10000)) / 100f + "%";
				orderOneUnion.add(orderObj);
			}
			//奖励
			int coff = type == 0 ? 1 : 2;//精英2倍
			int achiveGet = coff * (102 - orderId * 2) * config.getAchive() * (100 + getAwardCoff(playerId)) / 10000;
			player.getDataInfo().alterAchive(achiveGet);
			player.getDataInfo().commitSync();
			
			EventNotice notice = new EventNotice(ConstantsRadio.unionPet, ConstantsRadio.unionPet_award);
			notice.put("achiveGet", achiveGet);
			notice.broadcast(playerId);
			
			LogServer.recordLog(player, ConstantsLog.battle, 40501, achiveGet, type, union.getPetLv());
			
		}
		UnionPetBattle.getInstance().addAkOrder(unionId, orderOneUnion);
		UnionPetBattle.getInstance().commitSync();
		
		clear();
		
	}
	
	public void checkDead(long playerId) {
		if (unionPetFighter != null && unionPetFighter.getHp() <= 0) {
			synchronized (this) {
				if (unionPetFighter != null) {
					unionPetFighter = null;
					currentSamllDam = 0;
					orderDam();//
				}
			}
		}
	}
	
	private void clear() {
		playerAkMap.clear();
		playerDamMap.clear();
		playerDeadMap.clear();
		buffMap.clear();
		awardCoffMap.clear();
		UnionPetBattle.getInstance().remove(unionId);
	}
	
	public Collection<Long> getJoinIds(){
		return allPlayers.keySet();
	}

	public void removePlayer(long playerId) {
		allPlayers.remove(playerId);
	}
	

}
